﻿using System;

namespace NodeJS.http
{
    using NodeJS.net;
    using NodeJS.stream;

    /// <summary>
    /// This object is created internally and returned from http.request().
    /// It represents an in-progress request whose header has already been queued.
    /// The header is still mutable using the setHeader(name, value), getHeader(name), removeHeader(name) API.
    /// The actual header will be sent along with the first data chunk or when closing the connection.
    /// 
    /// To get the response, add a listener for 'response' to the request object.
    /// </summary>
    public class ClientRequest : Writable
    {
        /// <summary>
        /// Emitted when a response is received to this request. This event is emitted only once. The response argument will be an instance of http.IncomingMessage.
        /// </summary>
        [EvalAtCompile(Value = "response")]
        public const NodeEvent<IncomingMessage> RESPONSE = null;

        /// <summary>
        /// Emitted after a socket is assigned to this request.
        /// </summary>
        [EvalAtCompile(Value = "socket")]
        public const NodeEvent<Socket> SOCKET = null;

        /// <summary>
        /// Emitted each time a server responds to a request with a CONNECT method. If this event isn't being listened for, clients receiving a CONNECT method will have their connections closed.
        /// </summary>
        [EvalAtCompile(Value = "connect")]
        public const NodeEvent<IncomingMessage, Socket, Buffer> CONNECT = null;

        /// <summary>
        /// Emitted each time a server responds to a request with an upgrade. If this event isn't being listened for, clients receiving an upgrade header will have their connections closed.
        /// </summary>
        [EvalAtCompile(Value = "upgrade")]
        public const NodeEvent<IncomingMessage, Socket, Buffer> UPGRADE = null;

        /// <summary>
        /// Emitted when the server sends a '100 Continue' HTTP response, usually because the request contained 'Expect: 100-continue'. This is an instruction that the client should send the request body.
        /// </summary>
        [EvalAtCompile(Value = "continue")]
        public const NodeEvent CONTINUE = null;

        /// <summary>
        /// Sends a chunk of the body. By calling this method many times, the user can stream a request body to a server--in that case it is suggested to use the ['Transfer-Encoding', 'chunked'] header line when creating the request.
        /// </summary>
        /// <param name="chunk"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public bool Write(StringOrBuffer chunk, string encoding = "")
        {
            return false;
        }

        /// <summary>
        /// Finishes sending the request. If any parts of the body are unsent, it will flush them to the stream. If the request is chunked, this will send the terminating '0\r\n\r\n'.
        /// If data is specified, it is equivalent to calling request.write(data, encoding) followed by request.end().
        /// </summary>
        /// <param name="chunk"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public bool End(StringOrBuffer chunk = null, string encoding = "")
        {
            return false;
        }

        /// <summary>
        /// Aborts a request.
        /// </summary>
        public void Abort()
        {
        }

        /// <summary>
        /// Once a socket is assigned to this request and is connected socket.setTimeout() will be called.
        /// </summary>
        /// <param name="timeout"></param>
        /// <param name="callback"></param>
        public void SetTimeout(long timeout, Action callback = null)
        {
        }

        /// <summary>
        /// Once a socket is assigned to this request and is connected socket.setNoDelay() will be called.
        /// </summary>
        /// <param name="noDelay"></param>
        public void SetNoDelay(bool noDelay = true)
        {
        }

        /// <summary>
        /// Once a socket is assigned to this request and is connected socket.setKeepAlive() will be called.
        /// </summary>
        /// <param name="enable"></param>
        /// <param name="initialDelay"></param>
        public void SetSocketKeepAlive(bool enable = false, long initialDelay = 0)
        {
        }
    }
}
